#include "MPU6050.h"

I2Cx_Typedef *I2C1_pointer = NULL;
I2Cx_Typedef *I2C2_pointer = NULL;

#define EV5 I2C_EVENT_MASTER_MODE_SELECT
#define EV6 I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED
#define EV7 I2C_EVENT_MASTER_BYTE_RECEIVED
#define EV8 I2C_EVENT_MASTER_BYTE_TRANSMITTING
#define EV8_2 I2C_EVENT_MASTER_BYTE_TRANSMITTED

void I2C_waitBusy(I2C_TypeDef* I2Cx)
{
    uint16_t Timeout = 10000;
    while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))
    {
        Timeout--;
        if (Timeout == 0)
        {
            break;
        }
    }
}

void I2C_init(I2C_TypeDef *I2Cx, uint8_t slave_address)
{
    I2Cx_Typedef *I2Cx_pointer = malloc(sizeof(I2Cx_Typedef));
    // 变量初始化
    I2C_InitTypeDef I2C_InitStruct;
    GPIO_InitTypeDef GPIO_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;

    // 时钟配置
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
    // 配置 APB1EN 第 21 位为 I2C1EN 置1
    // PB6-SCL PB7-SDA
    if (I2Cx == I2C1)
    {
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
        NVIC_InitStruct.NVIC_IRQChannel = I2C1_EV_IRQn;
        if(I2C1_pointer != NULL)
        {
            free(I2C1_pointer->BUF);
            free(I2C1_pointer);
        }
        I2C1_pointer = I2Cx_pointer;
    }
    // 配置 APB1EN 第 22 位为 I2C2EN 置1
    // PB10-SCL PB11-SDA
    else if (I2Cx == I2C2)
    {
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
        NVIC_InitStruct.NVIC_IRQChannel = I2C2_EV_IRQn;
        if(I2C2_pointer != NULL)
        {
            free(I2C2_pointer->BUF);
            free(I2C2_pointer);
        }
        I2C2_pointer = I2Cx_pointer;
    }

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOB, &GPIO_InitStruct);
    GPIO_SetBits(GPIOB, GPIO_InitStruct.GPIO_Pin);

    // 初始化I2C事件中断
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    NVIC_Init(&NVIC_InitStruct);

    // 根据初始化条件，配置 I2C
    I2C_InitStruct.I2C_ClockSpeed = 90000;
    I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_16_9;
    I2C_InitStruct.I2C_OwnAddress1 = 0x00;
    I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init(I2Cx, &I2C_InitStruct);

    // 配置I2Cx_pointer
    I2Cx_pointer->BUF_SIZE = 30;
    I2Cx_pointer->BUF = malloc(I2Cx_pointer->BUF_SIZE);
    I2Cx_pointer->slave_address = slave_address;

    I2C_ITConfig(I2Cx, I2C_IT_EVT, ENABLE);
    I2C_ITConfig(I2Cx, I2C_IT_BUF, ENABLE);
    I2C_Cmd(I2Cx, ENABLE);
}

I2Cx_Typedef* I2C_pointer(I2C_TypeDef* I2Cx)
{
    if(I2Cx == I2C1)
    {
        return I2C1_pointer;
    }
    else if(I2Cx == I2C2)
    {
        return I2C2_pointer;
    }
}

/**
 * @brief 向寄存器中写入数据
 *
 * @param I2Cx 选中 I2C1 或 I2C2
 * @param reg 寄存器地址
 * @param Data 写入的数据
 */
void I2C_writeReg(I2C_TypeDef* I2Cx, uint8_t reg, uint8_t Data)
{
    I2Cx_Typedef* I2Cx_pointer = I2C_pointer(I2Cx);
    I2C_waitBusy(I2Cx);
    I2Cx_pointer->data = Data;
    I2Cx_pointer->send_flag = true;
    I2Cx_pointer->reg = reg;
    I2C_AcknowledgeConfig(I2Cx, ENABLE);
    I2C_GenerateSTART(I2Cx, ENABLE);
}

void I2C_readReg(I2C_TypeDef* I2Cx, uint8_t reg, uint8_t size)
{
    I2Cx_Typedef* I2Cx_pointer = I2C_pointer(I2Cx);
    I2C_waitBusy(I2Cx);
    I2Cx_pointer->reg = reg;
    I2Cx_pointer->receive_flag = true;
    I2Cx_pointer->receive_size = size;
    I2Cx_pointer->receive_i = 0;
    I2C_AcknowledgeConfig(I2Cx, ENABLE);
    I2C_GenerateSTART(I2Cx, ENABLE);
}

void I2C1_EV_IRQHandler(void)
{
    if (I2C1_pointer->receive_flag)
    {
        switch (I2C_GetLastEvent(I2C1))
        {
            // EV5 SB 开始位已发送
        case I2C_EVENT_MASTER_MODE_SELECT:
            I2C_Send7bitAddress(I2C1, I2C1_pointer->slave_address, I2C_Direction_Transmitter);
            break;
            // EV6 ADDR 地址已发送
        case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
            I2C_SendData(I2C1, I2C1_pointer->reg);
            break;
            // EV8_2 TxE BTF 发送缓存区空 发送完成
        case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
            I2C_GenerateSTART(I2C1, ENABLE);
            I2C1_pointer->receive_flag = false;
            break;
        }
    }
    else if (I2C1_pointer->receive_size)
    {
        switch (I2C_GetLastEvent(I2C1))
        {
            // EV5 SB 开始位已发送
        case I2C_EVENT_MASTER_MODE_SELECT:
            I2C_Send7bitAddress(I2C1, I2C1_pointer->slave_address, I2C_Direction_Receiver);
            break;
            // EV6 ADDR 地址已发送
        case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED:
            if (I2C1_pointer->receive_size == 1)
            {
                I2C_AcknowledgeConfig(I2C1, DISABLE);
                I2C_GenerateSTOP(I2C1, ENABLE);
            }
            break;
            // EV7 RxNE 接收缓存区非空
        case I2C_EVENT_MASTER_BYTE_RECEIVED:
            I2C1_pointer->BUF[I2C1_pointer->receive_i++] = I2C_ReceiveData(I2C1);
            if (I2C1_pointer->receive_size == 1 + I2C1_pointer->receive_i)
            {
                I2C_AcknowledgeConfig(I2C1, DISABLE);
                I2C_GenerateSTOP(I2C1, ENABLE);
            }
            break;
        }
    }
    else if (I2C1_pointer->send_flag)
    {
        switch (I2C_GetLastEvent(I2C1))
        {
            // EV5 SB 开始位已发送
        case I2C_EVENT_MASTER_MODE_SELECT:
            I2C_Send7bitAddress(I2C1, I2C1_pointer->slave_address, I2C_Direction_Transmitter);
            break;
            // EV6 ADDR 地址已发送
        case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
            I2C_SendData(I2C1, I2C1_pointer->reg);
            break;
        // EV8_2 TxE BTF 发送缓存区空 发送完成
        case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
            I2C_SendData(I2C1, I2C1_pointer->data);
            I2C_GenerateSTOP(I2C1, ENABLE);
            I2C1_pointer->send_flag = false;
            break;
        }
    }
}

void I2C2_EV_IRQHandler(void)
{
    if (I2C2_pointer->receive_flag)
    {
        switch (I2C_GetLastEvent(I2C2))
        {
            // EV5 SB 开始位已发送
        case I2C_EVENT_MASTER_MODE_SELECT:
            I2C_Send7bitAddress(I2C2, I2C2_pointer->slave_address, I2C_Direction_Transmitter);
            break;
            // EV6 ADDR 地址已发送
        case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
            I2C_SendData(I2C2, I2C2_pointer->reg);
            break;
            // EV8_2 TxE BTF 发送缓存区空 发送完成
        case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
            I2C_GenerateSTART(I2C2, ENABLE);
            I2C2_pointer->receive_flag = false;
            break;
        }
    }
    else if (I2C2_pointer->receive_size)
    {
        switch (I2C_GetLastEvent(I2C2))
        {
            // EV5 SB 开始位已发送
        case I2C_EVENT_MASTER_MODE_SELECT:
            I2C_Send7bitAddress(I2C2, I2C2_pointer->slave_address, I2C_Direction_Receiver);
            break;
            // EV6 ADDR 地址已发送
        case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED:
            if (I2C2_pointer->receive_size == 1)
            {
                I2C_AcknowledgeConfig(I2C2, DISABLE);
                I2C_GenerateSTOP(I2C2, ENABLE);
            }
            break;
            // EV7 RxNE 接收缓存区非空
        case I2C_EVENT_MASTER_BYTE_RECEIVED:
            I2C2_pointer->BUF[I2C2_pointer->receive_i++] = I2C_ReceiveData(I2C2);
            if (I2C2_pointer->receive_size == 1 + I2C2_pointer->receive_i)
            {
                I2C_AcknowledgeConfig(I2C2, DISABLE);
                I2C_GenerateSTOP(I2C2, ENABLE);
            }
            break;
        }
    }
    else if (I2C2_pointer->send_flag)
    {
        switch (I2C_GetLastEvent(I2C2))
        {
            // EV5 SB 开始位已发送
        case I2C_EVENT_MASTER_MODE_SELECT:
            I2C_Send7bitAddress(I2C2, I2C2_pointer->slave_address, I2C_Direction_Transmitter);
            break;
            // EV6 ADDR 地址已发送
        case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
            I2C_SendData(I2C2, I2C2_pointer->reg);
            break;
        // EV8_2 TxE BTF 发送缓存区空 发送完成
        case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
            I2C_SendData(I2C2, I2C2_pointer->data);
            I2C_GenerateSTOP(I2C2, ENABLE);
            I2C2_pointer->send_flag = false;
            break;
        }
    }
}
